package com.cqcetbbs.smartlab.cqcetbbs.view;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Build;
import android.support.annotation.IntDef;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.cqcetbbs.smartlab.cqcetbbs.R;
import com.wang.avi.indicator.BallBeatIndicator;
import com.wang.avi.indicator.BallClipRotateIndicator;
import com.wang.avi.indicator.BallClipRotateMultipleIndicator;
import com.wang.avi.indicator.BallClipRotatePulseIndicator;
import com.wang.avi.indicator.BallGridBeatIndicator;
import com.wang.avi.indicator.BallGridPulseIndicator;
import com.wang.avi.indicator.BallPulseIndicator;
import com.wang.avi.indicator.BallPulseRiseIndicator;
import com.wang.avi.indicator.BallPulseSyncIndicator;
import com.wang.avi.indicator.BallRotateIndicator;
import com.wang.avi.indicator.BallScaleIndicator;
import com.wang.avi.indicator.BallScaleMultipleIndicator;
import com.wang.avi.indicator.BallScaleRippleIndicator;
import com.wang.avi.indicator.BallScaleRippleMultipleIndicator;
import com.wang.avi.indicator.BallSpinFadeLoaderIndicator;
import com.wang.avi.indicator.BallTrianglePathIndicator;
import com.wang.avi.indicator.BallZigZagDeflectIndicator;
import com.wang.avi.indicator.BallZigZagIndicator;
import com.wang.avi.indicator.BaseIndicatorController;
import com.wang.avi.indicator.CubeTransitionIndicator;
import com.wang.avi.indicator.LineScaleIndicator;
import com.wang.avi.indicator.LineScalePartyIndicator;
import com.wang.avi.indicator.LineScalePulseOutIndicator;
import com.wang.avi.indicator.LineScalePulseOutRapidIndicator;
import com.wang.avi.indicator.LineSpinFadeLoaderIndicator;
import com.wang.avi.indicator.PacmanIndicator;
import com.wang.avi.indicator.SemiCircleSpinIndicator;
import com.wang.avi.indicator.SquareSpinIndicator;
import com.wang.avi.indicator.TriangleSkewSpinIndicator;

/**
 * Created by HeDongDong on 2017/3/29.
 * <p>
 * 自定义Listview,实现下拉刷新和上拉加载更多
 */

public class MyListView extends ListView implements OnScrollListener {

    private LoadMoreListener loadMoreListener;
    //是否可加载更多
    public boolean canLoadMore = true;
    //加载更多布局
    private LoadingMoreFooter loadingMoreFooter;
    //正在加载数据中
    private boolean isLoadingData = false;
    private int firstVisibleItem;

    public MyListView(Context context) {
        super(context, null);
        if (loadingMoreFooter != null) {
            loadingMoreFooter.setGone();
        }
        isLoadingData = false;
        init(context);
    }

    public MyListView(Context context, AttributeSet attrs) {
        super(context, attrs, 0);
        if (loadingMoreFooter != null) {
            loadingMoreFooter.setGone();
        }
        isLoadingData = false;
        init(context);
    }

    public MyListView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        if (loadingMoreFooter != null) {
            loadingMoreFooter.setGone();
        }
        isLoadingData = false;
        init(context);
    }

    private void init(Context context) {
        loadingMoreFooter = new LoadingMoreFooter(context);
        //设置自定义加载中效果
        ProgressView progressView = new ProgressView(context);
        progressView.setIndicatorId(ProgressView.BallPulse); //动画效果 自己可以尝试各种风格
        progressView.setIndicatorColor(ContextCompat.getColor(context, R.color.colorAccent));//动画颜色
        loadingMoreFooter.addFootLoadingView(progressView);
    }

    //移除加载更多布局
    public void removeFooter() {
        canLoadMore = false;
        this.removeFooterView(loadingMoreFooter);
    }

    //添加加载更多布局 在removeFooter()后调用
    public void addFooter() {
        canLoadMore = true;
        this.addFooterView(loadingMoreFooter);
    }

    //下拉刷新后初始化底部状态
    public void refreshComplete() {

    }

    //上拉加载后初始化底部状态
    public void loadMoreComplete() {
        if (loadingMoreFooter != null) {
            loadingMoreFooter.setGone();
        }
        isLoadingData = false;
    }


    //到底了
    public void loadMoreEnd() {
        if (loadingMoreFooter != null) {
            loadingMoreFooter.setEnd();
        }
    }

    //设置底部加载中效果
    public void setFootLoadingView(View view) {
        if (loadingMoreFooter != null) {
            loadingMoreFooter.addFootLoadingView(view);
        }
    }

    //设置加载更多监听
    public void setLoadMoreListener(LoadMoreListener listener) {
        loadMoreListener = listener;
        addFooterView(loadingMoreFooter);
        loadingMoreFooter.setGone();
        setOnScrollListener(this);
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        //判断 isLoadingData:不在加载中 ,scrollState:整个滚动事件结束，firstVisibleItem:条目至少上滑一条  canLoadMore:可以加载更多
        if (!isLoadingData && scrollState == OnScrollListener.SCROLL_STATE_IDLE &&
                firstVisibleItem != 0 && canLoadMore) {
            if (loadMoreListener != null) {
                if (loadingMoreFooter != null) {
                    loadingMoreFooter.setVisible();
                }
                isLoadingData = true;
                loadMoreListener.onLoadMore();
            }
        }
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int
            totalItemCount) {
        //firstVisibleItem表示在屏幕第一个ListItem(部分显示的ListItem也算)在整个ListView的位置（下标从0开始）
        this.firstVisibleItem = firstVisibleItem;
    }


    /**
     * 底部加载更多的布局
     */
    class LoadingMoreFooter extends LinearLayout {

        private Context context;
        private LinearLayout loading_view_layout;
        private LinearLayout end_layout;

        public LoadingMoreFooter(Context context) {
            super(context);
            this.context = context;
            initView(context);
        }

        /**
         * @param context
         * @param attrs
         */
        public LoadingMoreFooter(Context context, AttributeSet attrs) {
            super(context, attrs);
            initView(context);
        }

        public void initView(Context context) {
            setGravity(Gravity.CENTER);
            setLayoutParams(new AbsListView.LayoutParams(
                    AbsListView.LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.WRAP_CONTENT));
            LayoutInflater layoutInflater = LayoutInflater.from(context);
            View view = layoutInflater.inflate(R.layout.detail_listview_footer_layout,
                    null);
            loading_view_layout = (LinearLayout) view.findViewById(R.id.loading_view_layout);
            end_layout = (LinearLayout) view.findViewById(R.id.end_layout);


            addFootLoadingView(new ProgressBar(context, null, android.R.attr.progressBarStyle));

            TextView textView = new TextView(context);
            textView.setText("已经到底啦~");
            addFootEndView(textView);

            addView(view);
        }


        //设置底部加载中效果
        public void addFootLoadingView(View view) {
            loading_view_layout.removeAllViews();
            loading_view_layout.addView(view);
        }

        //设置底部到底了布局
        public void addFootEndView(View view) {
            end_layout.removeAllViews();
            end_layout.addView(view);
        }


        //设置已经没有更多数据
        public void setEnd() {
            setVisibility(VISIBLE);
            loading_view_layout.setVisibility(GONE);
            end_layout.setVisibility(VISIBLE);
        }


        public void setVisible() {
            setVisibility(VISIBLE);
            loading_view_layout.setVisibility(VISIBLE);
            end_layout.setVisibility(GONE);
        }


        public void setGone() {
            setVisibility(GONE);
        }


    }

    /**
     * 加载更多监听
     */
    public interface LoadMoreListener {

        void onLoadMore();

    }


    static class ProgressView extends View {
        //indicators
        public static final int BallPulse = 0;
        public static final int BallGridPulse = 1;
        public static final int BallClipRotate = 2;
        public static final int BallClipRotatePulse = 3;
        public static final int SquareSpin = 4;
        public static final int BallClipRotateMultiple = 5;
        public static final int BallPulseRise = 6;
        public static final int BallRotate = 7;
        public static final int CubeTransition = 8;
        public static final int BallZigZag = 9;
        public static final int BallZigZagDeflect = 10;
        public static final int BallTrianglePath = 11;
        public static final int BallScale = 12;
        public static final int LineScale = 13;
        public static final int LineScaleParty = 14;
        public static final int BallScaleMultiple = 15;
        public static final int BallPulseSync = 16;
        public static final int BallBeat = 17;
        public static final int LineScalePulseOut = 18;
        public static final int LineScalePulseOutRapid = 19;
        public static final int BallScaleRipple = 20;
        public static final int BallScaleRippleMultiple = 21;
        public static final int BallSpinFadeLoader = 22;
        public static final int LineSpinFadeLoader = 23;
        public static final int TriangleSkewSpin = 24;
        public static final int Pacman = 25;
        public static final int BallGridBeat = 26;
        public static final int SemiCircleSpin = 27;


        @IntDef(flag = true,
                value = {
                        BallPulse,
                        BallGridPulse,
                        BallClipRotate,
                        BallClipRotatePulse,
                        SquareSpin,
                        BallClipRotateMultiple,
                        BallPulseRise,
                        BallRotate,
                        CubeTransition,
                        BallZigZag,
                        BallZigZagDeflect,
                        BallTrianglePath,
                        BallScale,
                        LineScale,
                        LineScaleParty,
                        BallScaleMultiple,
                        BallPulseSync,
                        BallBeat,
                        LineScalePulseOut,
                        LineScalePulseOutRapid,
                        BallScaleRipple,
                        BallScaleRippleMultiple,
                        BallSpinFadeLoader,
                        LineSpinFadeLoader,
                        TriangleSkewSpin,
                        Pacman,
                        BallGridBeat,
                        SemiCircleSpin
                })
        public @interface Indicator {
        }

        //Sizes (with defaults in DP)
        public static final int DEFAULT_SIZE = 30;

        //attrs
        int mIndicatorId;
        int mIndicatorColor;

        Paint mPaint;

        BaseIndicatorController mIndicatorController;

        private boolean mHasAnimation;


        public ProgressView(Context context) {
            super(context);
            init(null, 0);
        }

        public ProgressView(Context context, AttributeSet attrs) {
            super(context, attrs);
            init(attrs, 0);
        }

        public ProgressView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init(attrs, defStyleAttr);
        }


        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
        public ProgressView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
            super(context, attrs, defStyleAttr, defStyleRes);
            init(attrs, defStyleAttr);
        }

        private void init(AttributeSet attrs, int defStyle) {
            TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.AVLoadingIndicatorView);
            mIndicatorId = a.getInt(R.styleable.AVLoadingIndicatorView_indicator, BallPulse);
            mIndicatorColor = a.getColor(R.styleable.AVLoadingIndicatorView_indicator_color, Color.WHITE);
            a.recycle();
            mPaint = new Paint();
            mPaint.setColor(mIndicatorColor);
            mPaint.setStyle(Paint.Style.FILL);
            mPaint.setAntiAlias(true);
            applyIndicator();
        }

        public void setIndicatorId(int indicatorId) {
            mIndicatorId = indicatorId;
            applyIndicator();
        }

        public void setIndicatorColor(int color) {
            mIndicatorColor = color;
            mPaint.setColor(mIndicatorColor);
            this.invalidate();
        }

        private void applyIndicator() {
            switch (mIndicatorId) {
                case BallPulse:
                    mIndicatorController = new BallPulseIndicator();
                    break;
                case BallGridPulse:
                    mIndicatorController = new BallGridPulseIndicator();
                    break;
                case BallClipRotate:
                    mIndicatorController = new BallClipRotateIndicator();
                    break;
                case BallClipRotatePulse:
                    mIndicatorController = new BallClipRotatePulseIndicator();
                    break;
                case SquareSpin:
                    mIndicatorController = new SquareSpinIndicator();
                    break;
                case BallClipRotateMultiple:
                    mIndicatorController = new BallClipRotateMultipleIndicator();
                    break;
                case BallPulseRise:
                    mIndicatorController = new BallPulseRiseIndicator();
                    break;
                case BallRotate:
                    mIndicatorController = new BallRotateIndicator();
                    break;
                case CubeTransition:
                    mIndicatorController = new CubeTransitionIndicator();
                    break;
                case BallZigZag:
                    mIndicatorController = new BallZigZagIndicator();
                    break;
                case BallZigZagDeflect:
                    mIndicatorController = new BallZigZagDeflectIndicator();
                    break;
                case BallTrianglePath:
                    mIndicatorController = new BallTrianglePathIndicator();
                    break;
                case BallScale:
                    mIndicatorController = new BallScaleIndicator();
                    break;
                case LineScale:
                    mIndicatorController = new LineScaleIndicator();
                    break;
                case LineScaleParty:
                    mIndicatorController = new LineScalePartyIndicator();
                    break;
                case BallScaleMultiple:
                    mIndicatorController = new BallScaleMultipleIndicator();
                    break;
                case BallPulseSync:
                    mIndicatorController = new BallPulseSyncIndicator();
                    break;
                case BallBeat:
                    mIndicatorController = new BallBeatIndicator();
                    break;
                case LineScalePulseOut:
                    mIndicatorController = new LineScalePulseOutIndicator();
                    break;
                case LineScalePulseOutRapid:
                    mIndicatorController = new LineScalePulseOutRapidIndicator();
                    break;
                case BallScaleRipple:
                    mIndicatorController = new BallScaleRippleIndicator();
                    break;
                case BallScaleRippleMultiple:
                    mIndicatorController = new BallScaleRippleMultipleIndicator();
                    break;
                case BallSpinFadeLoader:
                    mIndicatorController = new BallSpinFadeLoaderIndicator();
                    break;
                case LineSpinFadeLoader:
                    mIndicatorController = new LineSpinFadeLoaderIndicator();
                    break;
                case TriangleSkewSpin:
                    mIndicatorController = new TriangleSkewSpinIndicator();
                    break;
                case Pacman:
                    mIndicatorController = new PacmanIndicator();
                    break;
                case BallGridBeat:
                    mIndicatorController = new BallGridBeatIndicator();
                    break;
                case SemiCircleSpin:
                    mIndicatorController = new SemiCircleSpinIndicator();
                    break;
            }
            mIndicatorController.setTarget(this);
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            int width = measureDimension(dp2px(DEFAULT_SIZE), widthMeasureSpec);
            int height = measureDimension(dp2px(DEFAULT_SIZE), heightMeasureSpec);

//            int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2
//                    , MeasureSpec.AT_MOST);

            setMeasuredDimension(width, height);
//            super.onMeasure(widthMeasureSpec, expandSpec);
        }

        private int measureDimension(int defaultSize, int measureSpec) {
            int result = defaultSize;
            int specMode = MeasureSpec.getMode(measureSpec);
            int specSize = MeasureSpec.getSize(measureSpec);
            if (specMode == MeasureSpec.EXACTLY) {
                result = specSize;
            } else if (specMode == MeasureSpec.AT_MOST) {
                result = Math.min(defaultSize, specSize);
            } else {
                result = defaultSize;
            }
            return result;
        }

        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            drawIndicator(canvas);
        }

        @Override
        protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
            super.onLayout(changed, left, top, right, bottom);
            if (!mHasAnimation) {
                mHasAnimation = true;
                applyAnimation();
            }
        }

        @Override
        public void setVisibility(int v) {
            if (getVisibility() != v) {
                super.setVisibility(v);
                if (v == GONE || v == INVISIBLE) {
                    mIndicatorController.setAnimationStatus(BaseIndicatorController.AnimStatus.END);
                } else {
                    mIndicatorController.setAnimationStatus(BaseIndicatorController.AnimStatus.START);
                }
            }
        }

        @Override
        protected void onDetachedFromWindow() {
            super.onDetachedFromWindow();
            mIndicatorController.setAnimationStatus(BaseIndicatorController.AnimStatus.CANCEL);
        }

        @Override
        protected void onAttachedToWindow() {
            super.onAttachedToWindow();
            mIndicatorController.setAnimationStatus(BaseIndicatorController.AnimStatus.START);
        }

        void drawIndicator(Canvas canvas) {
            mIndicatorController.draw(canvas, mPaint);
        }

        void applyAnimation() {
            mIndicatorController.initAnimation();
        }

        private int dp2px(int dpValue) {
            return (int) getContext().getResources().getDisplayMetrics().density * dpValue;
        }
    }

//
//    @Override
//    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//        int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2
//                , MeasureSpec.AT_MOST);
//        super.onMeasure(widthMeasureSpec, expandSpec);
//    }
}
